/*
 * Copyright (c) 2024 endless-sky
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <gst/gst.h>
#define GST_USE_UNSTABLE_API
#include <gst/webrtc/webrtc.h>
#include <memory>
#include <map>
#include <mutex>
#include <thread>
#include <atomic>
#include <nlohmann/json.hpp>
#include "common_media_define.h"
#include "media_stream.h"
#include "web_server.h"
#include "utils_time_cost.h"
#include "utils_noncopyable.h"
#include "stream_flow_control.h"

namespace El {
namespace StreamService {

/**
 * @brief 智能框数据结构
 * 表示检测到的目标框信息
 */
struct BoundingBox {
    float x;           ///< 左上角x坐标 (相对于视频宽度的比例，0.0-1.0)
    float y;           ///< 左上角y坐标 (相对于视频高度的比例，0.0-1.0)
    float width;       ///< 框宽度 (相对于视频宽度的比例，0.0-1.0)
    float height;      ///< 框高度 (相对于视频高度的比例，0.0-1.0)
    float confidence;  ///< 置信度 (0.0-1.0)
    std::string label; ///< 目标标签
    int classId;       ///< 类别ID
};

/**
 * @brief 智能检测结果结构
 */
struct IntelligentResult {
    std::vector<BoundingBox> boxes; ///< 检测框列表
    uint64_t timestamp;             ///< 时间戳 (毫秒)
    uint32_t frameId;               ///< 帧ID
};

/**
 * @brief 媒体数据结构
 * 包含WebRTC客户端的媒体流相关数据
 */
struct MediaData {
    GstElement *appsrcVideo;                    ///< 视频应用源元素
    GstElement *appsrcAudio;                    ///< 音频应用源元素
    uint32_t channel;                           ///< 通道编号
    uint32_t streamType;                        ///< 流类型
    int streamHandle;                           ///< 流句柄
    Media::StreamSourcePtr streamSource;        ///< 流媒体源指针
    std::shared_ptr<StreamFlowControl> flowControl; ///< 流控管理器
};
using MediaDataPtr = std::shared_ptr<MediaData>;

/**
 * @brief 客户端连接结构
 * 包含单个WebRTC客户端连接的所有相关数据
 */
struct ClientConnection {
    void *wsConn;              ///< WebSocket连接指针
    GstElement *pipeline;      ///< GStreamer管道元素
    GstElement *webrtcElement; ///< WebRTC元素
    MediaDataPtr mediaData;    ///< 媒体数据指针
    Utils::TimeCost timeCost;  ///< 时间消耗统计

    /**
     * @brief 构造函数
     */
    ClientConnection() : wsConn(nullptr), pipeline(nullptr), webrtcElement(nullptr) {}
};

/**
 * @brief WebRTC流媒体服务器类
 * 提供基于GStreamer的WebRTC实时流媒体服务
 */
class StreamGstWebRTC {
    DISALLOW_COPY_AND_MOVE(StreamGstWebRTC);

public:
    /**
     * @brief 获取单例实例
     * @return StreamGstWebRTC& 单例实例引用
     */
    static StreamGstWebRTC &GetInstance();

    /**
     * @brief 启动WebRTC服务
     * @return bool 成功返回true，失败返回false
     */
    bool Start();

    /**
     * @brief 停止WebRTC服务
     */
    void Stop();

private:
    /**
     * @brief 私有构造函数（单例模式）
     */
    StreamGstWebRTC() = default;

    /**
     * @brief 析构函数
     */
    ~StreamGstWebRTC();

    /**
     * @brief 为客户端设置管道
     * @param clientConn 客户端连接对象
     */
    void SetupPipelineForClient(std::shared_ptr<ClientConnection> clientConn);

    /**
     * @brief 清理客户端连接
     * @param client 客户端连接对象
     */
    void CleanupClientConnection(std::shared_ptr<ClientConnection> client);

    /**
     * @brief 推送音视频帧到GStreamer
     * @param frame 媒体帧指针
     * @param stream 流数据对象
     */
    void PushFrame(const Media::MediaFramePtr &frame, MediaDataPtr stream);

    /**
     * @brief 发送SDP到对端
     * @param desc WebRTC会话描述
     * @param client 客户端连接对象
     */
    void SendSdpToPeer(GstWebRTCSessionDescription *desc, std::shared_ptr<ClientConnection> client);

    /**
     * @brief 发送ICE候选到对端
     * @param mlineindex 媒体行索引
     * @param candidate ICE候选字符串
     * @param client 客户端连接对象
     */
    void SendIceCandidateToPeer(guint mlineindex, gchar *candidate, std::shared_ptr<ClientConnection> client);

    /**
     * @brief Offer创建完成回调
     * @param promise GStreamer Promise对象
     * @param webrtc WebRTC元素
     * @param client 客户端连接对象
     */
    void OnOfferCreated(GstPromise *promise, GstElement *webrtc, ClientConnection *client);

    /**
     * @brief 协商需要回调
     * @param webrtc WebRTC元素
     * @param client 客户端连接对象
     */
    void OnNegotiationNeeded(GstElement *webrtc, ClientConnection *client);

    /**
     * @brief ICE候选回调
     * @param webrtc WebRTC元素（未使用）
     * @param mlineindex 媒体行索引
     * @param candidate ICE候选字符串
     * @param client 客户端连接对象
     */
    void OnIceCandidate([[maybe_unused]] GstElement *webrtc,
                        guint mlineindex,
                        gchar *candidate,
                        ClientConnection *client);

    /**
     * @brief 处理WebSocket事件
     * @param event WebSocket事件对象
     */
    void HandleWebSocketEvent(std::shared_ptr<El::WebServer::WebSocketEvent> &event);

    /**
     * @brief 处理WebSocket事件的主循环
     */
    void ProcessWebSocketEvents();

    /**
     * @brief 处理WebSocket消息
     * @param client 客户端连接对象
     * @param message 消息内容
     */
    void HandleWebSocketMessage(std::shared_ptr<ClientConnection> client, const std::string &message);

    /**
     * @brief 发送WebSocket文本消息
     * @param connection WebSocket连接指针
     * @param message 消息内容
     */
    void SendWebSocketTextMessage(void *connection, const std::string &message);

    /**
     * @brief 处理WebRTC Answer
     * @param client 客户端连接对象
     * @param params RPC参数
     * @param id RPC请求ID
     */
    void HandleWebRTCAnswer(std::shared_ptr<ClientConnection> client,
                            const nlohmann::json &params,
                            const nlohmann::json &id);

    /**
     * @brief 处理WebRTC ICE候选（请求模式）
     * @param client 客户端连接对象
     * @param params RPC参数
     * @param id RPC请求ID
     */
    void HandleWebRTCIceCandidate(std::shared_ptr<ClientConnection> client,
                                  const nlohmann::json &params,
                                  const nlohmann::json &id);

    /**
     * @brief 处理WebRTC ICE候选（通知模式）
     * @param client 客户端连接对象
     * @param params RPC参数
     */
    void HandleWebRTCIceCandidateNotification(std::shared_ptr<ClientConnection> client, const nlohmann::json &params);

    /**
     * @brief 处理WebRTC Ready信号
     * @param client 客户端连接对象
     * @param params RPC参数
     * @param id RPC请求ID
     */
    void HandleWebRTCReady(std::shared_ptr<ClientConnection> client,
                           const nlohmann::json &params,
                           const nlohmann::json &id);

    /**
     * @brief 发送RPC响应
     * @param client 客户端连接对象
     * @param id 请求ID
     * @param result 响应结果
     */
    void SendRpcResponse(std::shared_ptr<ClientConnection> client,
                         const nlohmann::json &id,
                         const nlohmann::json &result);

    /**
     * @brief 发送RPC错误响应
     * @param client 客户端连接对象
     * @param id 请求ID
     * @param code 错误码
     * @param message 错误消息
     * @param data 错误数据（可选）
     */
    void SendRpcError(std::shared_ptr<ClientConnection> client,
                      const nlohmann::json &id,
                      int code,
                      const std::string &message,
                      const nlohmann::json &data);

    /**
     * @brief 发送RPC通知
     * @param client 客户端连接对象
     * @param method 方法名
     * @param params 参数
     */
    void SendRpcNotification(std::shared_ptr<ClientConnection> client,
                             const std::string &method,
                             const nlohmann::json &params);

    /**
     * @brief 处理算法管理器返回的检测结果
     * @param result 算法检测结果的JSON数据
     */
    void HandleAlgoResult(const nlohmann::json &result);

    /**
     * @brief 发送智能框数据到前端
     * @param client 客户端连接对象
     * @param result 智能检测结果
     */
    void SendIntelligentBoxes(std::shared_ptr<ClientConnection> client, const IntelligentResult &result);

    /**
     * @brief 获取AAC采样率索引
     * @param sampleRate 采样率
     * @return uint8_t 采样率索引
     */
    uint8_t GetAacSampleRateIndex(int sampleRate);

private:
    /// 事件队列，用于处理WebSocket事件
    std::unique_ptr<El::Utils::BlockingQueue<std::shared_ptr<El::WebServer::WebSocketEvent>>> eventQueue_;
    std::unique_ptr<std::thread> processThread_;                      ///< 事件处理线程
    std::atomic<bool> running_{false};                                ///< 运行状态标志
    GstElement *pipeline_{nullptr};                                   ///< GStreamer管道（未使用）
    bool audioEnable_{false};                                         ///< 音频启用标志
    std::map<void *, std::shared_ptr<ClientConnection>> connections_; ///< 客户端连接映射表
    std::mutex connectionsMutex_;                                     ///< 连接互斥锁
    std::string audioCodec_;                                          ///< 音频编解码器类型
    int audioSampleRate_{8000};                                       ///< 音频采样率
    uint32_t frameCounter_{0};                                        ///< 帧计数器，用于生成frameId
};

} // namespace StreamService
} // namespace El